﻿#include <QStringBuilder>
#include <QInputDialog>
#include <QMessageBox>
#include <QTreeView>
#include <QTableView>
#include <QCloseEvent>
#include <QObject>
#include <QFileDialog>

#include "logger.h"
#include "my_defs.h"

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "appmanager.h"
#include "dbworker.h"
#include "styleswidget.h"
#include "csqltreemodel.h"
#include "stylesdialog.h"
#include "treemodel.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{   // setting up mainWindow
  ui->setupUi(this);

  connect(this, SIGNAL(searchNeeded()), this, SLOT(searchRecord()));
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::setupWindow()
{
  setStyleIdDelegates();
  if (appManager->dbWorker()->isDbLoaded())
    {
      linkModelsToViews();

      //      ui->treeViewAll->expandAll();
      //      for (int i=0; i<COL_COUNT; i++)
      //        ui->treeViewAll->resizeColumnToContents(i);
      //      ui->treeViewAll->collapseAll();

      ui->treeViewAll->setColumnWidth(1, 250);
      //      ui->treeViewAll->setWordWrap(true);
      ui->treeViewAll->setExpandsOnDoubleClick(true);

      selectedUniqId = -1;
      //    if (toolBar == NULL)
      //        setupToolbar();
      setupContextMenu();
    }
}

void MainWindow::linkModelsToViews()
{
  ui->tblViewQuery->setModel( appManager->dbWorker()->tabModel() );
  // setting tblViewQuery parameters
  ui->tblViewQuery->setAlternatingRowColors(true);
  ui->tblViewQuery->horizontalHeader()->setStretchLastSection(true);

  //  QList<QVariant> rootData;

  ui->tblViewQuery->setContextMenuPolicy(Qt::CustomContextMenu);

  // setting model treeModel to treeViewModel
  ui->treeViewAll->setModel( appManager->dbWorker()->treeModel() );

  ui->treeViewAll->setContextMenuPolicy(Qt::CustomContextMenu);

  ui->edtDbName->setText(appManager->dbWorker()->dbName());

  refreshViews();
}

void MainWindow::closeEvent(QCloseEvent *e)
{
  if (userReallyWantsToQuit()) {
      writeSettings();
      e->accept();
    } else {
      e->ignore();
    }
}

void MainWindow::setStyleIdDelegates()
{
  if(appManager->styleIdDelegate4Tab()!=NULL)
    {
      ui->tblViewQuery->setItemDelegateForColumn(2, appManager->styleIdDelegate4Tab());
    }
  if(appManager->styleIdDelegate4Tree()!=NULL)
    {
      ui->treeViewAll->setItemDelegateForColumn (2, appManager->styleIdDelegate4Tree());
    }
}

void MainWindow::searchRecord()
{
  if (    appManager->dbWorker()->isDbLoaded()
          && !ui->btnGo->text().isEmpty() )
    {
      if (appManager->dbWorker()->searchRowsCount() > 0)
        {
          // save columns state
          int colsWidth[COL_COUNT];
          for (int i = 0; i<COL_COUNT; i++) { colsWidth[i] = ui->tblViewQuery->columnWidth(i); }

          // search
          appManager->dbWorker()->search(ui->edtQuery->text());

          // restore columns state
          for (int i = 0; i<COL_COUNT; i++) { ui->tblViewQuery->setColumnWidth(i, colsWidth[i]); }
        }
      else
        {
          // search
          appManager->dbWorker()->search(ui->edtQuery->text());
        }

      ui->tblViewQuery->resizeRowsToContents();
      ui->tblViewQuery->resizeColumnsToContents();


      if (appManager->dbWorker()->isDbLoaded())
        ui->edtQueryCount->setText(QString("%1")
                                   .arg(appManager->dbWorker()->searchRowsCount()));
      ui->tblViewQuery->resizeColumnsToContents();
    }
}


void MainWindow::refreshViews()
{
  if (appManager->dbWorker()->isDbLoaded())
    {
      // refreshing tab
      emit searchNeeded();
      ui->tblViewQuery->resizeColumnsToContents();

      // refreshing tree
      //      ui->treeViewAll->setColumnWidth(0, 1000);
      //      ui->treeViewAll->allColumnsShowFocus();


      ui->edtRecordsCount->setText(QString("%1").arg(
                                     appManager->dbWorker()->treeModel()->childCount()));
    }
}

void MainWindow::showAddRecordForm()
{
  int nextFreeId = appManager->dbWorker()->findNextFreeId();

  if (nextFreeId == -1)
    {
      // no records in DB, so, create first one
      nextFreeId = 1;
    }

  appManager->recordForm()->morph2AddRecordForm(nextFreeId);
  appManager->recordForm()->show();
}

void MainWindow::showChangeRecordForm()
{
  Q_ASSERT(selectedUniqId >= 0);

  int styleId;
  QString name, comment;

  bool res = appManager->dbWorker()->getRecordByUniqId(selectedUniqId,
                                                       name,
                                                       styleId,
                                                       comment);
  if (res)
    {
      appManager->recordForm()->morph2ChangeRecordForm( selectedUniqId, name, styleId, comment );
      appManager->recordForm()->show();
    }
}


void MainWindow::on_btnGo_clicked()
{
  emit searchNeeded();
}

void MainWindow::on_commandLinkButton_clicked()
{
  appManager->settingsForm()->show();
}

void MainWindow::on_bntSaveQuery_clicked()
{
  bool isEmpty = appManager->dbWorker()->searchRowsCount() <= 0;
  if (isEmpty)
    {
      LOG( "MainWindow::on_bntSaveQuery_clicked()",
           "Не знайдено жодного співпадіння.",  "" );
      QMessageBox msg;
      msg.setInformativeText(QString("Не знайдено жодного співпадіння."));
      msg.setIcon(QMessageBox::Warning);
      msg.setStandardButtons(QMessageBox::Ok);
      msg.setDefaultButton(QMessageBox::Ok);
    }
  else
    {
      QString fileName =
          QFileDialog::getSaveFileName(this,
                                       "Оберіть куди зберегти вибірку",
                                       APP_DIR,
                                       "Веб-сторінка (*.html)");
      if (fileName.isEmpty())
        {
          return;
        }

      QFile file(fileName);

      if (!file.open(QIODevice::WriteOnly))
        {
          LOG( "MainWindow::on_bntSaveQuery_clicked()",
               "Не можу відкрити файл для запису",  fileName );
          QMessageBox msg;
          msg.setInformativeText(QString("Не вдалося відкрити файл для запису <br /><i>%1</i>")
                                 .arg(fileName));
          msg.setIcon(QMessageBox::Warning);
          msg.setStandardButtons(QMessageBox::Ok);
          msg.setDefaultButton(QMessageBox::Ok);
          msg.exec();
          return;
        }

      const MyTabModel *tm = appManager->dbWorker()->tabModel();

      QTextStream ts(&file);
      ts.setCodec("UTF-8");

      // output HEADER
      ts<<QString("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\"; charset=\"UTF-8\">"
                  "<title>QDisco -- Результат вибірки</title></head>"
                  "<body>"
                  "<h2>Результат виконання запиту</h2><hr />");
      ts<<QString("Платівки, що в назві містять <i>\"%1\"</i><br />")
          .arg( ui->edtQuery->text() );
      ts<<QString("з бази <i>\"%1\"</i>.<br /><hr />")
          .arg(appManager->dbWorker()->dbName());
      ts<<QString("Всього знайдено <b>%1 з %2</b>:<br />")
          .arg(ui->edtQueryCount->text())
          .arg(ui->edtRecordsCount->text());

      ts<<QString("<table>"); // begin TABLE
      ts<<QString("<tr>"); // begin TABLE HEADER
      for (int headCol = 0; headCol < COL_COUNT; headCol++)
        {
          ts<<QString("<td><center><b>%1</b></center></td>")
              .arg(COL_NAMES.at(headCol));
        }
      ts<<QString("</tr><br />"); // end TABLE HEADER

      // bein TABLE BODY
      for (int rowN = 0; rowN < tm->rowCount(); rowN++)
        {
          int uniqId = tm->record(rowN).value("uniqId").toInt();

          Q_UNUSED(uniqId);

          QString caption = tm->record(rowN).value("caption").toString();
          int styleId = tm->record(rowN).value("styleId").toInt();
          QString comment = tm->record(rowN).value("comment").toString();


          QString style = QString("<img src=\"%1\" alt=\"%2\" height=36 /> %2")
              .arg("file:///"+appManager->mStyles.value(styleId).img)
              .arg(appManager->mStyles.value(styleId).name);

          ts<<QString("<tr><td><center>%1</center></td> <td><big><b>%2</b></big></td>"
                      "<td>%3</td>  <td><i>%4</i></td></tr>")
              .arg(rowN + 1)
              .arg(caption)
              .arg(style)
              .arg(comment);
        }
      ts<<QString("</table></body></html>"); // end TABLE

      file.close();

      QMessageBox msg;
      msg.setText("<h2>Вибірку успішно збережено!</h2>");
      msg.setInformativeText(QString("Веб-сторінка з вибіркою успішно збережена і знаходиться: <i>%1</i>")
                             .arg(fileName));
      msg.setIcon(QMessageBox::Information);
      msg.setStandardButtons(QMessageBox::Ok);
      msg.setDefaultButton(QMessageBox::Ok);
      msg.exec();
    }
}

void MainWindow::showContextMenuForTblViewQuery(const QPoint &p)
{
  QModelIndex indx = ui->tblViewQuery->indexAt(p);
  bool needToBeVisible = indx != QModelIndex(); // <=> if there is 1.. rows in table

  //TODO: check conversation
  int uniqId = ui->tblViewQuery->model()->index(indx.row(), 0).data().toInt();
  QString name = ui->tblViewQuery->model()->index(indx.row(), 1).data().toString();

  selectedUniqId = uniqId;
  appManager->dbWorker()->setCurRec(uniqId);

  QString delRecStr(QString("Видалити запис (%1) - %2...").arg(uniqId).arg(name));
  delAct->setText(delRecStr);

  QString edtRecAct(QString("Редагувати запис (%1) - %2...").arg(uniqId).arg(name));
  edtAct->setText(edtRecAct);

  delAct->setVisible(needToBeVisible);
  edtAct->setVisible(needToBeVisible);

  recordMenu->exec( ui->tblViewQuery->viewport()->mapToGlobal(p) );
}

void MainWindow::showContextMenuForTree(const QPoint &p)
{
  QModelIndex indx = ui->treeViewAll->indexAt(p);

  bool needToBeVisible = indx != QModelIndex(); // <=> if there is 1.. rows in table

  if (!needToBeVisible || indx.parent()==QModelIndex()) { return; }

  //TODO: check conversation
  int uniqId = ui->treeViewAll->model()->index(indx.row(), 0, indx.parent()).data().toInt();
  //indx.data().toInt();
  QString name = ui->treeViewAll->model()->index(indx.row(), 1, indx.parent()).data().toString();
  //indx.data().toString();

  appManager->dbWorker()->setCurRec(uniqId);
  selectedUniqId = uniqId;

  QString delRecStr(QString("Видалити запис (%1) - %2...").arg(uniqId).arg(name));
  delAct->setText(delRecStr);

  QString edtRecAct(QString("Редагувати запис (%1) - %2...").arg(uniqId).arg(name));
  edtAct->setText(edtRecAct);

  delAct->setVisible(needToBeVisible);
  edtAct->setVisible(needToBeVisible);

  recordMenu->exec(ui->treeViewAll->viewport()->mapToGlobal(p));
}

bool MainWindow::userReallyWantsToQuit()
{
  QMessageBox::StandardButton reply;
  reply = QMessageBox::question(this, "Вихід з програми",
                                "Ви впевнеі що бажаєте завершити робту з прграмою?",
                                QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
  if (reply == QMessageBox::Yes) return true;

  return false;
}

void MainWindow::writeSettings()
{

}

void MainWindow::setupContextMenu()
{
  // setting up context menu for records
  recordMenu = new QMenu(this);

  // TODO: search icons

  edtAct = new QAction(QIcon::fromTheme("edit"), "Редагувати", this);
  connect(edtAct, SIGNAL(triggered()), this, SLOT(showChangeRecordForm()));

  delAct = new QAction(QIcon::fromTheme("edit-delete"), "Видалити", this);
  connect(delAct, SIGNAL(triggered()), appManager->dbWorker(), SLOT(deleteCurRecord()));

  newAct = new QAction(QIcon::fromTheme("document-new"), "Вставити новий запис", this);
  connect(newAct, SIGNAL(triggered()), this, SLOT(showAddRecordForm()));

  recordMenu->addAction(edtAct);
  recordMenu->addAction(delAct);
  recordMenu->addAction(newAct);

  connect(ui->tblViewQuery, SIGNAL(customContextMenuRequested(QPoint)),
          this, SLOT(showContextMenuForTblViewQuery(const QPoint &)));
  connect(ui->treeViewAll, SIGNAL(customContextMenuRequested(QPoint)),
          this, SLOT(showContextMenuForTree(QPoint)));
}

void MainWindow::export2txt(const QString fileName)
{
  QFile file(fileName);
  if (!file.open(QFile::WriteOnly))
    {
      LOG( "MainWindow::export2txt",
           "Не вдалося відкрити файл для запису!", fileName);
      return; // TODO: false
    }

  QTextStream out(&file);
  out.setCodec("UTF-8");

  // TODO: check constantness!!
  TreeModel const *tm = appManager->dbWorker()->treeModel();

  TreeItem *root = tm->rootItem;
  for (int styleN = 0; styleN < root->childCount(); styleN++)
    {
      TreeItem *ti = root->child(styleN);
      qDebug()//<<ti->data(0).toString()
          //<<ti->data(1).toString()
          <<ti->data(2).toString()
            //<<ti->data(3).toString()
            ;
      // cycle on all styles
      for (int rec = 0; rec < ti->childCount(); rec++)
        {
          TreeItem const *tti = ti->child(rec);
          QString csvStr(
                QString("%1, %2, %3, %4\n")
                .arg(tti->data(0).toString())
                .arg(tti->data(1).toString())
                .arg(tti->data(2).toString())
                .arg(tti->data(3).toString())
                );
          out<<csvStr.toUtf8();

          qDebug()<<tti->data(0).toString()
                 <<tti->data(1).toString()
                <<tti->data(2).toString()
               <<tti->data(3).toString();
        }
    }
  file.close();
}

void MainWindow::exort2html(const QString fileName)
{
  QFile file(fileName);
  if (!file.open(QFile::WriteOnly))
    {
      LOG( "MainWindow::export2txt",
           "Не вдалося відкрити файл для запису!", fileName);
      return; // TODO: false
    }

  QTextStream out(&file);
  out.setCodec("UTF-8");

  // TODO: check constantness!!
  TreeModel const *tm = appManager->dbWorker()->treeModel();


  // output HEADER
  out<<QString("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\"; charset=\"UTF-8\">"
               "<title>QDisco -- База %1</title></head>"
               "<body>"
               "<h2>База даних %1</h2><hr />")
       .arg(appManager->dbWorker()->dbName());
  out<<QString("Всього платівок: <b>%1</b>.<br />")
       .arg(ui->edtRecordsCount->text());

  TreeItem *root = tm->rootItem;
  for (int styleN = 0; styleN < root->childCount(); styleN++)
    {
      TreeItem *ti = root->child(styleN);
      // cycle on all styles

      int styleNum = ti->data(2).toInt();
      const Style curStyle = appManager->mStyles.value(styleNum);

      out<<QString("<hr /><h2><img src=\"%2\" alt=\"%1\" height=48 valign=center align=left/>%1</h2> <br />")
           .arg(curStyle.name != "" ? curStyle.name : "Не вказано стиль")
           .arg("file:///"+curStyle.img);

      // begin TABLE 4 STYLE
      out<<"<table>";
      for (int rec = 0; rec < ti->childCount(); rec++)
        {
          TreeItem const *tti = ti->child(rec);
          QString name = tti->data(1).toString();
          QString comment = tti->data(3).toString();

          QString csvStr = QString("<tr><td><center>%1</center></td> <td><big><b>%2</b></big></td>"
                                   "<td>%3</td>  <td><i>%4</i></td></tr>")
              .arg(rec + 1)
              .arg(name)
              .arg(curStyle.name)
              .arg(comment);

          out<<csvStr.toUtf8();

          //            QString csvStr(
          //                        QString("%1, %2, %3, %4\n")
          //                           .arg(tti->data(0).toString())
          //                           .arg()
          //                           .arg(tti->data(2).toString())
          //                           .arg(tti->data(3).toString())
          //                           );
          //            qDebug()<<tti->data(0).toString()
          //                    <<tti->data(1).toString()
          //                    <<tti->data(2).toString()
          //                    <<tti->data(3).toString();
        }
      out<<"</table>";
      // end TABLE 4 STYLE
    }
  out<<QString("</body></html>"); // end ALL
  file.close();
}

void MainWindow::setupMenu()
{
  // ACTIONS FOR DB
  // newDbAct
  newDbAct = new QAction(QIcon::fromTheme("document-new"),
                         "Створити нову базу", this);
  connect(newDbAct, SIGNAL(triggered()), this, SLOT(createNewDb()));
  // saveDbAct
  saveDbAct = new QAction(QIcon::fromTheme("document-save-as"),
                          "Зберегти базу як...", this);
  connect(saveDbAct, SIGNAL(triggered()), this, SLOT(saveDbAs()));
  // importDbAct
  importDbAct = new QAction(QIcon::fromTheme("document-save-as"),
                            "Імпортувати базу...", this); // TODO: check!
  connect(importDbAct, SIGNAL(triggered()), this, SLOT(importDb()));
  // exportDbAct
  exportDbAct = new QAction(QIcon::fromTheme("document-save-as"),
                            "Експортувати базу...", this); // TODO: check!
  connect(exportDbAct, SIGNAL(triggered()), this, SLOT(exportDb()));
  // loadDbAct
  loadDbAct = new QAction(QIcon::fromTheme("document-save-as"),
                          "Завантажити базу...", this);
  connect(loadDbAct, SIGNAL(triggered()), this, SLOT(loadDb()));

  // ACTIONS FOR SETTINGS
  settingsAct = new QAction(QIcon::fromTheme("hummer"),
                            "Налаштування", this);
  connect(settingsAct, SIGNAL(triggered()), appManager->settingsForm(), SLOT(show()));

  // EXIT ACTION
  exitAct = new QAction(QIcon::fromTheme("document-save-as"),
                        "Вихід", this);
  connect(exitAct, SIGNAL(triggered()), this, SLOT(exitApp()));

  // ACTIONS FOR HELPs
  helpAct = new QAction(QIcon::fromTheme("help"),
                        "Допомога", this);
  connect(helpAct, SIGNAL(triggered()), this, SLOT(showHelp()));

  aboutQtAct = new QAction(QIcon::fromTheme("Qt"),
                           "Про Qt", this);
  connect(aboutQtAct, SIGNAL(triggered()), this, SLOT(showQtHelp()));

  aboutAct = new QAction(QIcon::fromTheme("About"),
                         "Про програму", this);
  connect(aboutAct, SIGNAL(triggered()), this, SLOT(showAbout()));

  // CONFIGURING MAIN MENU
  // for DB
  dbMenu = menuBar()->addMenu("База даних");
  dbMenu->addAction(newDbAct);
  dbMenu->addAction(loadDbAct);
  dbMenu->addAction(saveDbAct);
  dbMenu->addSeparator();
  dbMenu->addAction(importDbAct);
  dbMenu->addAction(exportDbAct);
  dbMenu->addSeparator();
  dbMenu->addAction(exitAct);

  // settings
  menuBar()->addAction(settingsAct);

  // for help
  helpMenu = menuBar()->addMenu("Довідка");
  helpMenu->addAction(helpAct);
  helpMenu->addAction(aboutAct);
  helpMenu->addAction(aboutQtAct);
}


void MainWindow::changeEvent(QEvent *e)
{
  if (e->WindowStateChange || e->Resize)
    {
      //        refreshViews();
    }
}


void MainWindow::createNewDb()
{
  // calling input dialog window, getting new DB name
  bool ok;
  QString newDBName = QInputDialog::getText(this, "Введіть назву нової бази даних",
                                            "Назва: ", QLineEdit::Normal, "DB_", &ok);
  if (!ok)
    {
      LOG( "MainWindow, QInputDialog", "Не введено назву нової бази даних, чи не натиснуто Ок в діалоговому вікні", "" );
      QMessageBox::warning(this, "QDisco",
                           "Потрібно <b>ввести назву</b> файлу БД і <b>натиснути</b> Оk!", QMessageBox::Ok);
      return;
    }

  appManager->dbWorker()->closeCurrentDb();

  // got new db name, creating it
  bool createDbResult;
  createDbResult = appManager->dbWorker()->createDB(
        QString("%1%2bases%2%4")
        .arg(APP_DIR)
        .arg(QDir::separator())
        .arg(newDBName),
        MY_TABLE_STRUCT_IN_SQL );

  if (createDbResult)
    {
      setupWindow();

      LOG( "MainWindow, createDB", QString("Базу з назвою <i>%1</i> успішно створено.").arg(newDBName), "" );
      QMessageBox::information(this, "QDisco",
                               QString("Базу з назвою <i>%1</i> успішно створено.").arg(newDBName), QMessageBox::Ok);
    } else {
      LOG( "MainWindow, createDB", QString("Базу з назвою <i>%1</i> не було створено!").arg(newDBName), "" );
      QMessageBox::critical(this, "QDisco", QString("Базу з назвою <i>%1</i> не було створено!<br/>"
                                                    "Для отримання інформації -- перегляньте файл з логами.").arg(newDBName), QMessageBox::Ok);
    }
}

void MainWindow::saveDbAs()
{
  QString fileName = QFileDialog::getSaveFileName(this, "Зберегти поточну базу даних як...",
                                                  APP_DIR,
                                                  "База даних sqlite (*.sqlite)");
  if (fileName.isEmpty() || fileName.isNull())
    {
      LOG("MainWindow::saveDbAs", "Не обрано файлу для збереження!", "");
      return;
    }
  bool saved = appManager->dbWorker()->saveDbAs(fileName);
  if (saved)
    {
      LOG("MainWindow::saveDbAs", "Базу було успішно перезбережено!", "");
    }
  appManager->dbWorker()->closeCurrentDb();
  if (!appManager->dbWorker()->openDb(fileName))
    {
      // problem while opening DB!
      LOG("MainWindow::saveDbAs", "Базу не було відкрито.", fileName);
      return;
    }

  this->linkModelsToViews();

  LOG("MainWindow::saveDbAs", QString("Базу було успішно відкрито з файлу <i>%1/</i>!").arg(fileName), "");
}

void MainWindow::importDb()
{
  QMessageBox msg;
  if (appManager->dbWorker()->isDbLoaded())
    {
      msg.setText("<h2>QDisco - Підтвердження імпорту БД</h2>");
      msg.setIcon(QMessageBox::Question);
      msg.setInformativeText(QString("Зараз поточна БД <i>(%1)</i> буде збережена і закрита.<br />"
                                     "Продовжити процедуру імпортування БД?")
                             .arg(appManager->dbWorker()->workDB()->databaseName()));
      msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
      msg.setDefaultButton(QMessageBox::Yes);
      int ret = msg.exec();
      if (ret == QMessageBox::Yes)
        {
          // save & close current DB, create new DB, and begin import
          appManager->dbWorker()->closeCurrentDb();
        }
      else
        {
          return;
        }
    }
  bool ok = false;
  QString newDbName = QInputDialog::getText(this, "Імпорт БД",
                                            "Вкажіть ім’я нової БД:",
                                            QLineEdit::Normal,
                                            "DB_", &ok);
  if (!ok || newDbName.isEmpty())
    {
      LOG( "MainWindow::importDb", "Не введено назву нової БД", "" );
      //        appManager->dbWorker()->refreshAllModels();
      return;
    }

  if (!appManager->dbWorker()->createDB(newDbName, MY_TABLE_STRUCT_IN_SQL))
    {
      LOG( "MainWindow::importDb", "Виникла проблема при створенні БД!", "" );

      msg.setText("Проблема з імпортом БД");
      msg.setIcon(QMessageBox::Critical);
      msg.setInformativeText(QString("Неможливо створити базу даних з вказаним ім’ям: <i>%1</i>").arg(newDbName));
      msg.setStandardButtons(QMessageBox::Ok);
      msg.setDefaultButton(QMessageBox::Ok);
      msg.exec();
      return;
    }

  QString fileName = QFileDialog::getOpenFileName(this,
                                                  "Оберіть текстовий файл для імпорту:",
                                                  APP_DIR,
                                                  "Текстовий файл (*.txt)");
  if (fileName.isEmpty())
    {
      LOG( "MainWindow::importDb()", "Не обрано файлу для імпорту!", "" );

      //        appManager->dbWorker()->refreshAllModels();
      return;
    }

  QTime begin = QTime::currentTime();

  QFile txtFile(fileName);
  if (!txtFile.open(QFile::Text | QFile::ReadOnly))
    {
      LOG( "MainWindow::importDb()", "Проблема читання файлу!", "" );
      txtFile.remove();
      return;
    }

  QTextStream stream(&txtFile);

  QVariantList uniqIds, names, styleIds, comments;

  int i = 0;
  while (!stream.atEnd())
    {
      i++;
      QString str = stream.readLine();
      // TODO: delete
      if (str=="\n") break;
      QStringList strLst = str.split(",");
      foreach(QString tmp, strLst)
        tmp = tmp.toUtf8().simplified();

      int uniqId = strLst.at(0).toInt();
      QString name = strLst.at(1);
      int styleId = strLst.at(2).toInt();
      QString comment = strLst.at(3);

      uniqIds << uniqId;
      names << name;
      styleIds << styleId;
      comments << comment;
      //        appManager->dbWorker()->insertRecord(strLst.at(0).toInt(),
      //                                             strLst.at(1),
      //                                             strLst.at(2).toInt(),
      //                                             strLst.at(3),
      //                                             false);
    }


  qDebug() << "addeed records" << i;
  BatchInsertThread *thread = new BatchInsertThread(uniqIds,
                                                    names,
                                                    styleIds,
                                                    comments);
  connect(thread, SIGNAL(started()), this, SLOT(importThreadStarted()));
  connect(thread, SIGNAL(finished()), this, SLOT(importThreadFinished()));

  QTime end = QTime::currentTime();

  LOG("Потік створено","","");
  thread->start();

  LOG("Час виконання імпорту", QString("%1 секунд.").arg(begin.secsTo(end)), "");
}


void MainWindow::exportDb()
{
  if (!appManager->dbWorker()->isDbLoaded())
    {
      QMessageBox msg;
      msg.setText("<h2>Не відкрито БД!</h2>");
      msg.setInformativeText(QString("Для того щоб експортувати БД потрібно її "
                                     "спершу відкрити."));
      msg.setIcon(QMessageBox::Information);
      msg.setStandardButtons(QMessageBox::Ok);
      msg.setDefaultButton(QMessageBox::Ok);
      msg.exec();
      return;
    }
  else
    {
      QString fileName =
          QFileDialog::getSaveFileName(this,
                                       "Оберіть файл для експорту",
                                       APP_DIR,
                                       "Текстовий CSV (*.txt *.csv);;"
                                       "Веб-сторінка (*.htm *.html)");
      if (fileName.isEmpty())
        {
          return;
        }
      else
        {
          QFileInfo fileInfo(fileName);
          if (fileInfo.suffix()=="txt" || fileInfo.suffix()=="csv")
            {
              // export to txt
              export2txt(fileName);
            }
          else
            {
              // export to htm
              exort2html(fileName);
            }
          QMessageBox msg;
          msg.setText("<h2>Базу успішно експортовано!</h2>");
          msg.setInformativeText(QString("Всі записи <i>(%1 шт.)</i> з бази <br /><i>%2<i/>"
                                         "були спішно експортовані у файл<br /><i>%3<i/>")
                                 .arg(ui->edtRecordsCount->text())
                                 .arg(ui->edtDbName->text())
                                 .arg(fileName));
          msg.setIcon(QMessageBox::Information);
          msg.setStandardButtons(QMessageBox::Ok);
          msg.setDefaultButton(QMessageBox::Ok);
          msg.exec();
        }
    }
}

void MainWindow::loadDb()
{
  QMessageBox msg;

  if (appManager->dbWorker()->isDbLoaded())
    {
      msg.setText("<h2>QDisco - Підтвердження завантаження БД</h2>");
      msg.setInformativeText(QString("Зараз поточна БД <i>(%1)</i> буде збережена і закрита."
                                     "Продовжити процедуру завантаження БД?")
                             .arg(appManager->dbWorker()->workDB()->databaseName()));
      msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
      msg.setDefaultButton(QMessageBox::Yes);
      int ret = msg.exec();
      if (ret == QMessageBox::Yes)
        {
          // save & close current DB, create new DB, and begin import
          appManager->dbWorker()->closeCurrentDb();
        }
      else
        {
          return;
        }
    }

  QString fileName = QFileDialog::getOpenFileName(this,
                                                  "Оберіть файл БД для завантаження:",
                                                  APP_DIR,
                                                  "Файл БД sqlite (*.sqlite)");
  if (fileName.isEmpty())
    {
      LOG("MainWindow::loadDb()", "Не обрано файл для завантаження", "");
      msg.setText("<h2>QDisco - Не обрано файлу</h2>");
      msg.setInformativeText("Файл для завантаження БД не було обрано!");
      msg.setStandardButtons(QMessageBox::Ok);
      msg.setDefaultButton(QMessageBox::Ok);
      msg.exec();
      return;
    }
  LOG("MainWindow::loadDb()", "БД завантажується з файлу", fileName);
  appManager->dbWorker()->openDb(fileName);
  this->linkModelsToViews();
  this->refreshViews();
}

void MainWindow::exitApp()
{
  this->close();
}

void MainWindow::showHelp()
{
}

void MainWindow::showAbout()
{
  QMessageBox::about(this, "Про QDisco",
                     "<h2>Програма <b>QDisco</b></h2>"
                     "Розроблена <b>tr0 (<a href=mailto:troyan3@gmail.com>troyan3 [злий пес] gmail.com</a>)</b><br />"
                     "Офіційний сайт програми: <a href=www.leningrad.www.tochka.ru>www.leningrad.www.tochka.ru</a></br />"
                     "<hr /> Програма призначена для ведення баз даних платівок, дисків, та ін. в музичному "
                     "магазині.<br />"
                     "<hr /> Написана на <b>Qt 4.8</b>, бази даних - <b>SQLite</b>."
                     "<hr /> <center><small>Доступна для ОС: <b>GNU/Linux, MacOS, Windows.</b></small></center>");
}

void MainWindow::importThreadStarted()
{
  this->setEnabled(false);
  this->setStatusTip("Відбувається імпортування БД. Зачекайте, будь ласка.");
    QApplication::instance()->processEvents();
}

void MainWindow::importThreadFinished()
{
  this->setEnabled(true);
  this->setStatusTip("Імпортування БД завершено.");

    appManager->dbWorker()->refreshAllModels();
    this->setupWindow();
    this->refreshViews();
}


void MainWindow::showQtHelp()
{
  QMessageBox::aboutQt(this, "Про Qt");
}
